package com.open.capacity.salary.service.impl;

import com.open.capacity.model.system.LoginAppUser;
import com.open.capacity.model.system.SysUser;
import com.open.capacity.salary.constant.Globals;
import com.open.capacity.salary.dao.GzRecordSalaryHistoryDao;
import com.open.capacity.salary.dto.GzRecordSalaryDto;
import com.open.capacity.salary.dto.ImportResult;
import com.open.capacity.salary.entity.*;
import com.open.capacity.salary.service.*;
import com.open.capacity.salary.util.POIExcelUtil;
import com.open.capacity.user.dao.SysUserHistoryDao;
import com.open.capacity.user.model.SysDepartment;
import com.open.capacity.user.model.SysDictData;
import com.open.capacity.user.model.SysUserHistory;
import com.open.capacity.user.service.SysDepartmentService;
import com.open.capacity.user.service.SysDictDataService;
import com.open.capacity.user.service.SysUserService;
import com.open.capacity.utils.*;
import com.open.capacity.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.*;
import org.mvel2.MVEL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.open.capacity.commons.PageResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.open.capacity.commons.CodeEnum;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.collections4.MapUtils;

import com.open.capacity.salary.dao.GzRecordSalaryDao;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@Service
public class GzRecordSalaryServiceImpl implements GzRecordSalaryService {

    @Autowired
    private GzRecordSalaryDao gzRecordSalaryDao;

    @Autowired
    private GzRecordSalaryHistoryDao gzRecordSalaryHistoryDao;

    @Autowired
    private GzItemService gzItemService;

    @Autowired
    private SysDepartmentService departmentService;

    @Autowired
    private SysUserService userService;

    @Autowired
    private GzEnableMonthService gzEnableMonthService;

    @Autowired
    private GzZtUserService ztUserService;

    @Autowired
    private SysDictDataService dictService;

    @Autowired
    private GzStandSubsidyService standSubsidyService;

    @Autowired
    private SysUserHistoryDao userHistoryDao;


    private static final String JICHUJIXIAO_ITEM_CODE = "37";
    private static final String GONGWUJIAOTONG_ITEM_CODE = "29";
    private static final String TONGXUNFEI_ITEM_CODE = "31";

    private static final String JICHUJIXIAO_ITEM_EXT_CODE = "38";
    private static final String GONGWUJIAOTONG_ITEM_EXT_CODE = "30";
    private static final String TONGXUNFEI_ITEM_EXT_CODE = "32";

    /**
     * 添加
     *
     * @param gzRecordSalary
     */
    public int save(GzRecordSalaryDto gzRecordSalary) {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(gzRecordSalary.getCompanyId(), gzRecordSalary.getZtId()).getCurrentMonth();
        List<GzItem> itemList = gzItemService.findByZtId(gzRecordSalary.getCompanyId(), gzRecordSalary.getZtId());
        for (GzRecordSalary item : gzRecordSalary.getRecords()) {
            //先删除
            gzRecordSalaryDao.deleteByUserItem(gzRecordSalary.getCompanyId(), gzRecordSalary.getZtId(), currentMonth, gzRecordSalary.getUserid(), item.getItemId().replace("col_", ""));
            if (item.getValue() != null) {
                item.setCompanyId(gzRecordSalary.getCompanyId());
                item.setZtId(gzRecordSalary.getZtId());
                item.setMonth(currentMonth);
                item.setItemId(item.getItemId().replace("col_", ""));
                item.setItemName(itemList.stream().filter(t -> t.getId().equals(item.getItemId())).findFirst().get().getName());
                item.setUserId(gzRecordSalary.getUserid());
                item.setUserCode(gzRecordSalary.getUsercode());
                item.setUserName(gzRecordSalary.getUsername());
                gzRecordSalaryDao.save(item);
            }
        }

        return 1;
    }

    @Override
    public int nextMonth(String companyId, String ztId, String currentMonth) {
        String nextMonth = DateUtil.getNextMonth(currentMonth);
        return gzRecordSalaryDao.nextMonth(companyId, ztId, currentMonth, nextMonth);
    }

    @Override
    public int preMonth(String companyId, String ztId, String month) {
        return gzRecordSalaryDao.deleteByZtId(companyId, ztId, month);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchSave(String companyId, String ztId, List<GzRecordSalary> list) {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();

        //gzRecordSalaryDao.deleteByZtId(companyId, ztId, currentMonth);

        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        List<GzRecordSalary> insertList = new ArrayList<>();

        for (GzRecordSalary item : list) {
            item.setCompanyId(companyId);
            item.setZtId(ztId);
            item.setDepartmentName(item.getDepartmentname());
            item.setMonth(currentMonth);
            item.setItemId(item.getItemId().replace("col_", ""));
            item.setItemName(itemList.stream().filter(t -> t.getId().equals(item.getItemId())).findFirst().get().getName());
            item.setUserId(item.getUserid());
            item.setUserCode(item.getUsercode());
            item.setUserName(item.getUsername());
            insertList.add(item);
        }
        //批量保存
        for (String userId : list.stream().map(GzRecordSalary::getUserId).distinct().collect(Collectors.toList())) {
            //先删除
            gzRecordSalaryDao.deleteByUser(companyId, ztId, currentMonth, userId);
        }
        if (CollectionUtils.isNotEmpty(insertList)) {
            gzRecordSalaryDao.batchsave(insertList);
        }


        //删除不在账套的职工记录
        //gzRecordSalaryDao.deleteNotInZtUser(companyId, ztId, currentMonth);

        return list.size();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int edit(String companyId, String ztId, String operate, String itemId, BigDecimal money) {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        List<GzRecordSalary> salaryList = gzRecordSalaryDao.findByItem(companyId, ztId, currentMonth, itemId);
        List<GzZtUser> ztUsers = ztUserService.findByZtId(companyId, ztId);

        for (GzZtUser user : ztUsers) {
            GzRecordSalary item;
            Optional<GzRecordSalary> op = salaryList.stream().filter(t -> t.getUserId().equals(user.getUserId())).findFirst();

            if (op.isPresent()) {
                item = op.get();
                switch (operate) {
                    case "add":
                        item.setValue(BigDecimalUtil.getData(item.getValue()).add(money));
                        break;
                    case "reduce":
                        item.setValue(BigDecimalUtil.getData(item.getValue()).subtract(money));
                        break;
                    case "multipe":
                        item.setValue(BigDecimalUtil.getData(item.getValue()).multiply(money));
                        break;
                    case "divide":
                        item.setValue(BigDecimalUtil.getData(item.getValue()).divide(money));
                        break;
                    case "set":
                        item.setValue(money);
                        break;
                }
                gzRecordSalaryDao.update(item);
            } else {
                item = new GzRecordSalary();
                item.setCompanyId(companyId);
                item.setZtId(ztId);
                item.setMonth(currentMonth);

                SysUser userModel = userService.findById(user.getUserId());
                if (userModel == null) {
                    continue;
                }
                SysDepartment department = departmentService.findById(userModel.getDepartmentId());
                Assert.notNull(department, "找不到部门：" + userModel.getDepartmentId());

                item.setDepartmentName(department.getFullName());
                item.setUserId(userModel.getId());
                item.setUserCode(userModel.getUserCode());
                item.setUserName(userModel.getRealName());
                item.setItemId(itemId);
                item.setItemName(itemList.stream().filter(t -> t.getId().equals(item.getItemId())).findFirst().get().getName());

                switch (operate) {
                    case "add":
                        item.setValue(money);
                        break;
                    case "reduce":
                        item.setValue(money.negate());
                        break;
                    case "multipe":
                        item.setValue(BigDecimal.ZERO);
                        break;
                    case "divide":
                        item.setValue(BigDecimal.ZERO);
                        break;
                    case "set":
                        item.setValue(money);
                        break;
                }


                gzRecordSalaryDao.save(item);
            }
        }
        return ztUsers.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int calc(String companyId, String ztId) {
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();

        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        Map<String, Object> params = new HashMap<>();
        params.put("companyId", companyId);
        params.put("ztId", ztId);
        params.put("itemColumns", itemList.stream().map(GzItem::getId).collect(Collectors.toList()));
        params.put("month", currentMonth);
        //缓存数据
        List<GzRecordSalary> caches = gzRecordSalaryDao.findSimpleByZtId(companyId, ztId, currentMonth);
        List<Map<String, Object>> recordList = gzRecordSalaryDao.findAll(params);

        //删除不在账套的职工记录
        //gzRecordSalaryDao.deleteNotInZtUser(companyId, ztId, currentMonth);

        List<GzRecordSalary> updateList = new ArrayList<>();
        List<GzRecordSalary> insertList = new ArrayList<>();
        for (GzItem item : itemList) {
            if (StringUtil.isNotEmpty(item.getFormula())) {
                for (Map<String, Object> map : recordList) {
                    String userId = map.get("userid").toString();
                    String formula = item.getFormula();

                    Map<String, Object> data = new HashMap<>();

                    if (!formula.equals("0")) {
                        for (GzItem item2 : itemList) {
                            if (formula.contains(item2.getName())) {
                                Optional<GzRecordSalary> gz = caches.stream().filter(t -> t.getUserId().equals(userId) && t.getItemId().equals(item2.getId())).findFirst();
                                BigDecimal value = BigDecimal.ZERO;
                                if (gz.isPresent()) {
                                    value = gz.get().getValue();
                                }
                                data.put("$" + item2.getName().replaceAll("（", "_1").replaceAll("）", "_2").replaceAll("、", "_3").replaceAll("/", "_4"), value);
                            }
                        }
                    }


                    if (!formula.equals("0")) {
                        //计算公式
                        GzRecordSalary model = new GzRecordSalary();
                        model.setCompanyId(companyId);
                        model.setDepartmentName(map.get("departmentname").toString());
                        model.setMonth(currentMonth);
                        model.setUserId(map.get("userid").toString());
                        model.setUserCode(map.get("usercode").toString());
                        model.setUserName(map.get("username").toString());
                        model.setItemId(item.getId());
                        model.setItemName(item.getName());
                        Object result = MVEL.eval(item.getFormula().replaceAll("（", "_1").replaceAll("）", "_2").replaceAll("、", "_3").replaceAll("/", "_4"), data);
                        model.setValue(new BigDecimal(result.toString()));
                        Optional<GzRecordSalary> gz = caches.stream().filter(t -> t.getUserId().equals(map.get("userid").toString()) && t.getItemId().equals(item.getId())).findFirst();
                        if (map.containsKey("col_" + item.getId()) && gz.isPresent()) {
                            model.setId(gz.get().getId());
                            //gzRecordSalaryDao.update(model);
                            updateList.add(model);
                            Optional<GzRecordSalary> gzCache = caches.stream().filter(t -> t.getUserId().equals(map.get("userid").toString()) && t.getItemId().equals(item.getId())).findFirst();
                            if (gz.isPresent()) {
                                caches.remove(gzCache.get());
                            }
                        } else {
                            model.setZtId(ztId);
                            //gzRecordSalaryDao.save(model);
                            insertList.add(model);
                        }
                        caches.add(model);
                    }
                }
            }
        }

        //批量更新
        if (CollectionUtils.isNotEmpty(updateList)) {
            gzRecordSalaryDao.batchupdate(updateList);
        }
        if (CollectionUtils.isNotEmpty(insertList)) {
            gzRecordSalaryDao.batchsave(insertList);
        }

        //海珠特有
        //calcUserLevelOrJobs(companyId, ztId, currentMonth, caches);

        return 1;
    }

    //根据用户的工资待遇计算工资
    private void calcUserLevelOrJobs(String companyId, String ztId, String month, List<GzRecordSalary> caches) {
        List<GzRecordSalary> updateList = new ArrayList<>();
        List<GzRecordSalary> insertList = new ArrayList<>();

        List<SysDictData> data1 = dictService.findDictDatas("GzInJobBasicPerformances");//在职基础绩效
        List<SysDictData> data2 = dictService.findDictDatas("GzRetireBasicPerformances");//退休基础绩效
        List<SysDictData> data3 = dictService.findDictDatas("GzCarSubsidys");//车补
        List<GzStandSubsidy> data4 = standSubsidyService.findAll(new HashMap<>());//通讯费

        List<String> userIds = caches.stream().map(GzRecordSalary::getUserId).distinct().collect(Collectors.toList());
        for (String userid : userIds) {
            SysUserHistory user = userService.findLastHistory(userid);
            if (user == null || user.getActionTime() == null) {
                continue;
            }

            long count = ChronoUnit.MONTHS.between(LocalDate.parse(DateUtil.getFirstDayOfMonth(DateUtil.formatDate(user.getActionTime()))), LocalDate.parse(month + "-01"));

            Optional<GzRecordSalary> op1 = caches.stream().filter(t -> t.getUserId().equals(userid) && t.getItemId().equals(JICHUJIXIAO_ITEM_CODE)).findFirst();  //司法人员基础绩效
            Optional<GzRecordSalary> op1_ext = caches.stream().filter(t -> t.getUserId().equals(userid) && t.getItemId().equals(JICHUJIXIAO_ITEM_EXT_CODE)).findFirst();  //司法人员基础绩效补发
//            Optional<GzRecordSalary> op2 = caches.stream().filter(t -> t.getUserId().equals(userid) && t.getItemId().equals("计划生育奖励补助")).findFirst();
            Optional<GzRecordSalary> op3 = caches.stream().filter(t -> t.getUserId().equals(userid) && t.getItemId().equals(GONGWUJIAOTONG_ITEM_CODE)).findFirst(); //公务交通补贴
            Optional<GzRecordSalary> op3_ext = caches.stream().filter(t -> t.getUserId().equals(userid) && t.getItemId().equals(GONGWUJIAOTONG_ITEM_EXT_CODE)).findFirst(); //公务交通补贴补发
            Optional<GzRecordSalary> op4 = caches.stream().filter(t -> t.getUserId().equals(userid) && t.getItemId().equals(TONGXUNFEI_ITEM_CODE)).findFirst(); //通讯费
            Optional<GzRecordSalary> op4_ext = caches.stream().filter(t -> t.getUserId().equals(userid) && t.getItemId().equals(TONGXUNFEI_ITEM_EXT_CODE)).findFirst(); //通讯费补发


            //在职基础绩效
            if (StringUtil.isNotEmpty(user.getLevels())) {
                Optional<SysDictData> d1 = data1.stream().filter(t -> t.getName().equals(user.getLevels())).findFirst();
                //Assert.isTrue(d1.isPresent(), "找不到工资待遇" + user.getLevels());
                BigDecimal _v = BigDecimal.ZERO;
                if (d1.isPresent()) {
                    _v = new BigDecimal(d1.get().getValue());
                }

                insertOrUpdateItemRecord(insertList, updateList, op1, companyId, ztId, user, month, JICHUJIXIAO_ITEM_CODE, "司法人员基础绩效", _v);

                //判断是否需要补发
                if (count > 0) {
                    BigDecimal _add = calcDictBetweenDiff(data1, user);
                    if (_add.compareTo(BigDecimal.ZERO) > 0) {
                        insertOrUpdateItemRecord(insertList, updateList, op1_ext, companyId, ztId, user, month, JICHUJIXIAO_ITEM_EXT_CODE, "司法人员基础绩效补发", _add.multiply(BigDecimal.valueOf(count)));
                    }
                }
            }

            //公务交通补贴
            if (StringUtil.isNotEmpty(user.getLevels())) {
                Optional<SysDictData> d3 = data3.stream().filter(t -> t.getName().equals(user.getLevels())).findFirst();
                //Assert.isTrue(d3.isPresent(), "找不到工资待遇" + user.getLevels());
                BigDecimal _v = BigDecimal.ZERO;
                if (d3.isPresent()) {
                    _v = new BigDecimal(d3.get().getValue());
                }

                insertOrUpdateItemRecord(insertList, updateList, op3, companyId, ztId, user, month, GONGWUJIAOTONG_ITEM_CODE, "公务交通补贴", _v);

                //判断是否需要补发
                if (count > 0) {
                    BigDecimal _add = calcDictBetweenDiff(data3, user);
                    if (_add.compareTo(BigDecimal.ZERO) > 0) {
                        insertOrUpdateItemRecord(insertList, updateList, op3_ext, companyId, ztId, user, month, GONGWUJIAOTONG_ITEM_EXT_CODE, "公务交通补贴补发", _add.multiply(BigDecimal.valueOf(count)));
                    }
                }
            }

            //通讯费
            if (StringUtil.isNotEmpty(user.getJob())) {
                Optional<GzStandSubsidy> d4 = data4.stream().filter(t -> t.getLevels().equals(user.getLevels())).findFirst();
//                Optional<GzStandSubsidy> d4 = data4.stream().filter(t -> t.getLevels().equals(user.getLevels()) && t.getJob().equals(user.getJob())).findFirst();
//                Assert.isTrue(d4.isPresent(), "找不到工资待遇" + user.getLevels() + "实际职务" + user.getJob());
                BigDecimal _v = BigDecimal.ZERO;
                if (d4.isPresent()) {
                    _v = d4.get().getValue();
                }

                insertOrUpdateItemRecord(insertList, updateList, op4, companyId, ztId, user, month, TONGXUNFEI_ITEM_CODE, "通讯费", _v);

                //判断是否需要补发
                if (count > 0) {
                    BigDecimal _add = calcSubsidyidyBetweenDiff(data4, user);
                    if (_add.compareTo(BigDecimal.ZERO) > 0) {
                        insertOrUpdateItemRecord(insertList, updateList, op4_ext, companyId, ztId, user, month, TONGXUNFEI_ITEM_EXT_CODE, "通讯费补发", _add.multiply(BigDecimal.valueOf(count)));
                    }
                }
            }
        }
        //批量更新
        if (CollectionUtils.isNotEmpty(updateList)) {
            gzRecordSalaryDao.batchupdate(updateList);
        }
        if (CollectionUtils.isNotEmpty(insertList)) {
            gzRecordSalaryDao.batchsave(insertList);
        }
    }

    //计算基本工资绩效补发/车补
    private BigDecimal calcDictBetweenDiff(List<SysDictData> dictData, SysUserHistory history) {
        Optional<SysDictData> first = dictData.stream().filter(t -> t.getName().equals(history.getLevels())).findFirst();
        if (!first.isPresent()) {
            return BigDecimal.ZERO;
        }
        Optional<SysDictData> second = dictData.stream().filter(t -> t.getName().equals(history.getLevels2())).findFirst();
        if (second.isPresent()) {
            return new BigDecimal(first.get().getValue()).subtract(new BigDecimal(second.get().getValue()));
        } else {
            return new BigDecimal(first.get().getValue());
        }
    }

    //计算通讯费补发
    private BigDecimal calcSubsidyidyBetweenDiff(List<GzStandSubsidy> dictData, SysUserHistory history) {
        Optional<GzStandSubsidy> first = dictData.stream().filter(t -> t.getLevels().equals(history.getLevels())).findFirst();
        if (!first.isPresent()) {
            return BigDecimal.ZERO;
        }
        Optional<GzStandSubsidy> second = dictData.stream().filter(t -> t.getLevels().equals(history.getLevels2())).findFirst();
        if (second.isPresent()) {
            return first.get().getValue().subtract(second.get().getValue());
        } else {
            return first.get().getValue();
        }
    }

    //新增or更新工资记录
    private void insertOrUpdateItemRecord(List<GzRecordSalary> insertList, List<GzRecordSalary> updateList, Optional<GzRecordSalary> optional, String companyId, String ztId, SysUserHistory user, String month, String itemId, String itemName, BigDecimal _v) {
        if (optional.isPresent()) {
            optional.get().setValue(_v);
            updateList.add(optional.get());
        } else {
            GzRecordSalary gz1 = new GzRecordSalary();
            gz1.setCompanyId(companyId);
            gz1.setZtId(ztId);
            gz1.setDepartmentName(user.getDepartmentName());
            gz1.setMonth(month);
            gz1.setUserId(user.getUserid());
            gz1.setUserCode(user.getUserCode());
            gz1.setUserName(user.getRealName());
            gz1.setItemId(itemId);
            gz1.setItemName(itemName);
            gz1.setValue(_v);
            insertList.add(gz1);
        }
    }

    /**
     * 删除
     *
     * @param id
     */
    public int delete(String id) {
        return gzRecordSalaryDao.delete(id);
    }

    @Override
    public int deleteNotInZtUser(String companyId, String ztId, String month) {
        return gzRecordSalaryDao.deleteNotInZtUser(companyId, ztId, month);
    }

    @Override
    @Transactional
    public int transferHistory() {
        String month = DateUtil.getMonth(DateUtil.formatDate(new Date()), "yyyy-MM", -1 * Globals.GZDATA_SAVE_MONTH);
        log.info("开始检查工资数据是否超过3个月");
        int c = gzRecordSalaryHistoryDao.batchTransfer(month);
        c = gzRecordSalaryDao.removeTransfer(month);
        return 1;
    }

    /**
     * 查询记录
     *
     * @param id
     * @return
     */
    public GzRecordSalary findById(String id) {
        return gzRecordSalaryDao.findById(id);
    }

    @Override
    public List<Map<String, Object>> findByUserid(String companyId, String ztId, String userid) {
        Map<String, Object> params = new HashMap<>();
        params.put("companyId", companyId);
        params.put("ztId", ztId);
        params.put("userId", userid);
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        params.put("itemColumns", itemList.stream().map(GzItem::getId).collect(Collectors.toList()));
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();
        params.put("month", currentMonth);

        if (params.containsKey("departmentId") && StringUtil.isNotEmpty(params.get("departmentId").toString())) {
            String departmentId = params.get("departmentId").toString();
            params.put("departmentId", Arrays.asList(departmentId.split(",")));
        } else {
            params.remove("departmentId");
        }
        if (params.containsKey("userCategory") && StringUtil.isNotEmpty(params.get("userCategory").toString())) {
            String userCategory = params.get("userCategory").toString();
            params.put("userCategory", Arrays.asList(userCategory.split(",")));
        } else {
            params.remove("userCategory");
        }

        return gzRecordSalaryDao.findAll(params);
    }

    /**
     * 分页
     *
     * @param params
     * @return
     */
    public PageResult<Map<String, Object>> pageAll(Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String ztId = params.get("ztId").toString();
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();
        params.put("month", currentMonth);
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        params.put("itemColumns", itemList.stream().map(GzItem::getId).collect(Collectors.toList()));

        //设置分页信息，分别是当前页数和每页显示的总记录数【记住：必须在mapper接口中的方法执行之前设置该分页信息】
        if (MapUtils.getInteger(params, "page") != null && MapUtils.getInteger(params, "limit") != null)
            PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);

        String sidx = params.get("sidx").toString();
        String sord = params.get("sord").toString();
        if (StringUtil.isNotEmpty(sidx) && StringUtil.isNotEmpty(sord)) {
            params.put("orderby", sidx + " " + sord);
        }
        if (params.containsKey("departmentId") && StringUtil.isNotEmpty(params.get("departmentId").toString())) {
            String departmentId = params.get("departmentId").toString();
            params.put("departmentId", Arrays.asList(departmentId.split(",")));
        } else {
            params.remove("departmentId");
        }
        if (params.containsKey("userCategory") && StringUtil.isNotEmpty(params.get("userCategory").toString())) {
            String userCategory = params.get("userCategory").toString();
            params.put("userCategory", Arrays.asList(userCategory.split(",")));
        } else {
            params.remove("userCategory");
        }
        List<Map<String, Object>> list = gzRecordSalaryDao.findAll(params);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo(list);

        return PageResult.<Map<String, Object>>builder().data(pageInfo.getList()).resp_code(CodeEnum.SUCCESS.getCode()).count(pageInfo.getTotal()).build();
    }

    /**
     * 列表
     *
     * @param params
     * @return
     */
    public List<Map<String, Object>> findAll(Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String ztId = params.get("ztId").toString();
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        params.put("itemColumns", itemList.stream().map(GzItem::getId).collect(Collectors.toList()));
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();
        params.put("month", currentMonth);

        if (params.containsKey("departmentId") && StringUtil.isNotEmpty(params.get("departmentId").toString())) {
            String departmentId = params.get("departmentId").toString();
            params.put("departmentId", Arrays.asList(departmentId.split(",")));
        } else {
            params.remove("departmentId");
        }
        if (params.containsKey("userCategory") && StringUtil.isNotEmpty(params.get("userCategory").toString())) {
            String userCategory = params.get("userCategory").toString();
            params.put("userCategory", Arrays.asList(userCategory.split(",")));
        } else {
            params.remove("userCategory");
        }

        return gzRecordSalaryDao.findAll(params);
    }


    @Override
    public List<String> getExcelSheets(MultipartFile multipartFile) throws IOException {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();
        InputStream inputStream = multipartFile.getInputStream();
        Workbook wb = WorkbookFactory.create(inputStream);
        int sheetCount = wb.getNumberOfSheets();
        List<String> sheetNames = new ArrayList<>();
        for (int i = 0; i < sheetCount; i++) {
            sheetNames.add(wb.getSheetName(i));
        }
        return sheetNames;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public long importExcel(String companyId, String ztId, String category, String sheetName, MultipartFile multipartFile) throws Exception {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();
        InputStream inputStream = multipartFile.getInputStream();
        Workbook wb = WorkbookFactory.create(inputStream);

        Sheet sheet = wb.getSheet(sheetName);
        // 获取最大行数(或者sheet.getLastRowNum())
        int rownum = sheet.getPhysicalNumberOfRows();
        // 获取第一行(表头)
        Row row = sheet.getRow(0);
        Assert.notNull(row, "数据格式不合法");
        // 获取最大列数
        int column = row.getPhysicalNumberOfCells();

        List<GzRecordSalary> data = new ArrayList<>();
        Map<Integer, String> dyheader = new HashMap<>();
        // 表头校验
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        List<GzZtUser> ztUserList = ztUserService.findByZtId(companyId, ztId);

        for (int i = 0; i < column; i++) {
            Cell cell = row.getCell(i);
            if (cell != null && itemList.stream().map(GzItem::getName).collect(Collectors.toList()).contains(cell.getStringCellValue())) {
                dyheader.put(i, "col_" + itemList.stream().filter(t -> t.getName().equals(cell.getStringCellValue())).findFirst().get().getId());
            }
        }
        Map<String, SysUser> userCacheMap = new HashMap<>();

        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();

        long count = 0;
        // 处理行数据
        for (int i = 1; i < rownum; i++) {
            row = sheet.getRow(i);
            // 遇到空行则结束
            if (row == null) {
                break;
            }

            String userName = POIExcelUtil.getString(row.getCell(0));
            SysUser user = userCacheMap.get(userName) != null ? userCacheMap.get(userName) : userService.findByGzName(companyId, category, userName);
            Assert.notNull(user, "找不到员工：" + userName);
            if (ztUserList.stream().map(GzZtUser::getUserId).collect(Collectors.toList()).contains(user.getId())) {
                for (Map.Entry<Integer, String> entry : dyheader.entrySet()) {
                    Cell cell = row.getCell(entry.getKey());
                    if (cell != null && cell.getCellType() != CellType.BLANK) {
                        GzRecordSalary item = new GzRecordSalary();
                        item.setCompanyId(companyId);
                        item.setZtId(ztId);
                        item.setDepartmentName(user.getDepartmentName());
                        item.setMonth(currentMonth);
                        userCacheMap.put(userName, user);
                        item.setUserId(user.getId());
                        item.setUserCode(user.getUserCode());
                        item.setUserName(userName);
                        item.setItemId(entry.getValue());
                        try {
                            item.setValue(POIExcelUtil.getNumber(cell));
                        } catch (NumberFormatException e) {
                            Assert.isTrue(false, "第" + (cell.getRowIndex() + 1) + "行," + (cell.getColumnIndex() + 1) + "列金额非法");
                        }
                        data.add(item);
                    }
                }
            }
        }
        for (GzRecordSalary item : data) {
            GzRecordSalary model = gzRecordSalaryDao.findByUserItem(companyId, ztId, currentMonth, item.getUserId(), item.getItemId().replace("col_", ""));
            if (model == null) {
                item.setCompanyId(companyId);
                item.setZtId(ztId);
                item.setMonth(currentMonth);
                item.setItemId(item.getItemId().replace("col_", ""));
                item.setItemName(itemList.stream().filter(t -> t.getId().equals(item.getItemId())).findFirst().get().getName());
                gzRecordSalaryDao.save(item);
            } else {
                model.setValue(item.getValue());
                gzRecordSalaryDao.update(model);
            }
        }
        count = data.stream().map(GzRecordSalary::getUserId).collect(Collectors.toList()).stream().distinct().count();
        return count;
    }

    @Override
    public ImportResult importExcelExt(String companyId, String ztId, String category, String sheetName, MultipartFile multipartFile) throws Exception {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();
        InputStream inputStream = multipartFile.getInputStream();
        Workbook wb = WorkbookFactory.create(inputStream);

        Sheet sheet = wb.getSheet(sheetName);
        // 获取最大行数(或者sheet.getLastRowNum())
        int rownum = sheet.getPhysicalNumberOfRows();
        // 获取第一行(表头)
        Row row;
        Row row2 = sheet.getRow(1);
        Row row3 = sheet.getRow(2);
        Assert.notNull(row3, "数据格式不合法");
        // 获取最大列数
        int column = row3.getPhysicalNumberOfCells();

        List<GzRecordSalary> data = new ArrayList<>();
        Map<Integer, String> dyheader = new HashMap<>();
        // 表头校验
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        List<GzZtUser> ztUserList = ztUserService.findByZtId(companyId, ztId);

        for (int i = 0; i < column; i++) {
            Cell cell = row3.getCell(i);
            String _tempColumn = cell.getStringCellValue().trim().replaceAll("\n", "");
            if (cell != null && itemList.stream().map(GzItem::getName).collect(Collectors.toList()).contains(_tempColumn)) {
                dyheader.put(i, "col_" + itemList.stream().filter(t -> t.getName().equals(_tempColumn)).findFirst().get().getId());
            }
        }
        for (int i = 0; i < column; i++) {
            Cell cell = row2.getCell(i);
            String _tempColumn = cell.getStringCellValue().trim().replaceAll("\n", "");
            if (cell != null && itemList.stream().map(GzItem::getName).collect(Collectors.toList()).contains(_tempColumn)) {
                dyheader.put(i, "col_" + itemList.stream().filter(t -> t.getName().equals(_tempColumn)).findFirst().get().getId());
            }
        }

        //根据名称查部门用户id缓存map
        Map<String, SysUser> userCacheMap = new HashMap<>();

        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();

        long count = 0;
        // 处理行数据

        List<SysUserHistory> userHistoryList = new ArrayList<>();
        for (int i = 4; i < rownum; i++) {
            row = sheet.getRow(i);
            // 遇到空行则结束
            if (row == null) {
                break;
            }

            String userName = POIExcelUtil.getString(row.getCell(0));//姓名
            String idnumber = POIExcelUtil.getString(row.getCell(2));//身份证号码
            String levels = POIExcelUtil.getString(row.getCell(4));//工资待遇
            String job = POIExcelUtil.getString(row.getCell(5));//职务
            String technicalLevel = POIExcelUtil.getString(row.getCell(6));//档次

            SysUser user = userCacheMap.get(idnumber) != null ? userCacheMap.get(idnumber) : userService.findByCode(companyId, idnumber);
            if (user.getJob() == null) {
                user.setJob("");
            }
            Assert.notNull(user, "找不到员工：" + userName);
            if (!levels.equals(user.getLevels()) || !job.equals(user.getJob())) {
                userHistoryList.add(new SysUserHistory(user.getId(), levels, job, technicalLevel, user.getLevels(), user.getJob(), user.getTechnicalLevel()));
            }
            if (ztUserList.stream().map(GzZtUser::getUserId).collect(Collectors.toList()).contains(user.getId())) {
                for (Map.Entry<Integer, String> entry : dyheader.entrySet()) {
                    Cell cell = row.getCell(entry.getKey());
                    if (cell != null && cell.getCellType() != CellType.BLANK) {
                        GzRecordSalary item = new GzRecordSalary();
                        item.setCompanyId(companyId);
                        item.setZtId(ztId);
                        item.setDepartmentName(user.getDepartmentName());
                        item.setMonth(currentMonth);
                        userCacheMap.put(idnumber, user);
                        item.setUserId(user.getId());
                        item.setUserCode(user.getUserCode());
                        item.setUserName(userName);
                        item.setItemId(entry.getValue());
                        try {
                            BigDecimal value = POIExcelUtil.getNumber(cell);
                            if (value.compareTo(BigDecimal.ZERO) != 0) {
                                item.setValue(value);
                                data.add(item);
                            }
                        } catch (NumberFormatException e) {
                            Assert.isTrue(false, "第" + (cell.getRowIndex() + 1) + "行," + (cell.getColumnIndex() + 1) + "列金额非法");
                        }

                    }
                }
            }
        }

        for (GzRecordSalary item : data) {
            GzRecordSalary model = gzRecordSalaryDao.findByUserItem(companyId, ztId, currentMonth, item.getUserId(), item.getItemId().replace("col_", ""));
            if (model == null) {
                item.setCompanyId(companyId);
                item.setZtId(ztId);
                item.setMonth(currentMonth);
                item.setItemId(item.getItemId().replace("col_", ""));
                item.setItemName(itemList.stream().filter(t -> t.getId().equals(item.getItemId())).findFirst().get().getName());
                gzRecordSalaryDao.save(item);
            } else {
                model.setValue(item.getValue());
                gzRecordSalaryDao.update(model);
            }
        }
        count = data.stream().map(GzRecordSalary::getUserId).collect(Collectors.toList()).stream().distinct().count();


        ImportResult result = new ImportResult();
        result.setCount(count);
        if (CollectionUtils.isNotEmpty(userHistoryList)) {
            result.setHasChange(true);
            result.setUserids(userHistoryList.stream().map(SysUserHistory::getUserid).collect(Collectors.toList()));
            //记录员工晋升变动记录
            //CompletableFuture.runAsync(() -> {
            recordUserHistory(userHistoryList);
            //});
        }


        return result;
    }


    //记录用户晋升记录
    private void recordUserHistory(List<SysUserHistory> userList) {
        for (SysUserHistory history : userList) {
            userService.saveHistory(history);
        }
    }
}
